import hashlib
import os
import re
import uuid
from datetime import datetime, timedelta

from django.db import transaction
from django.utils.translation import gettext_lazy as _
from rest_framework.decorators import permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from rest_framework_simplejwt.views import TokenObtainPairView

from apps.accounts.filters import UserFilter
from apps.accounts.handlers import init_menu
from apps.accounts.models import User, SystemSettings, UserPasswordHistory
from apps.accounts.serializers import UserSerializer, APITokenObtainPairSerializer, SystemSettingsSerializer, \
    UserInfoSerializer, APIUserLoginTokenObtainPairSerializer
from apps.rbac.models import RoleMenuOperate
from bases.messages import MSG_50001_ERROR_USER
from bases.response import SuccessResponse, FailResponse
from bases.viewsets import APIModelViewSet, APIUpdateOnlyViewSet, APIReadOnlyViewSet
from utils.system_settings.constant import INITIAL_PASSWORD, PASSWORD_VALID_DAYS, PASSWORD_REGEX, \
    DISABLE_PASSWORD_DUPLICATION_TIMES
from utils.system_settings.handler import get_system_setting
from utils.utils import create_folder


class APITokenObtainPairView(TokenObtainPairView):
    """
    用户登录请求API
    """
    serializer_class = APITokenObtainPairSerializer


class APIUserLoginTokenObtainPairView(TokenObtainPairView):
    """
    用户登录请求API
    """
    serializer_class = APIUserLoginTokenObtainPairSerializer


class UserViewSet(APIModelViewSet):
    """
    用户增删改查通用API
    """
    queryset = User.objects.all().order_by('-is_active', 'id')
    serializer_class = UserSerializer
    filter_class = UserFilter


class UserInfoViewSet(APIReadOnlyViewSet):
    """
    用户增删改查通用API
    """
    queryset = User.objects.all().order_by('-is_active', 'id')
    serializer_class = UserInfoSerializer


class SystemSettingsViewSet(APIUpdateOnlyViewSet):
    """
    系统参数改查通用接口
    """
    queryset = SystemSettings.objects.filter(is_active=True).order_by('id')
    serializer_class = SystemSettingsSerializer


class ResetPassword(APIView):
    """
    密码重置API
    方法：POST
    参数：user (用户ID)
    """

    @transaction.atomic
    def post(self, request):
        user_id = request.data['user']

        initial_password = get_system_setting(INITIAL_PASSWORD)
        days = get_system_setting(PASSWORD_VALID_DAYS)
        curr_date = datetime.now().date()

        user = User.objects.get(id=user_id)
        user.set_password(initial_password)
        user.valid_date = curr_date
        user.invalid_date = curr_date + timedelta(days=int(days))
        user.init_status = True
        user.save()
        return SuccessResponse()


class UserMenuPermission(APIView):

    def get(self, request):
        menu_list = init_menu(request)
        return SuccessResponse(menu_list)


@permission_classes((AllowAny,))
class UpdatePassword(APIView):
    """
    密码修改API
    方法：POST
    参数：user_id, old_password、new_password
    """

    @transaction.atomic
    def post(self, request):
        user_name = request.data['user_name']
        old_password = request.data['old_password']
        new_password = request.data['new_password']

        md5 = hashlib.md5()
        md5.update(new_password.encode("utf8"))
        md5_password = md5.hexdigest()

        password_regex = get_system_setting(PASSWORD_REGEX)
        if password_regex:
            if not re.match(password_regex, new_password):
                # Translators: 密码强度不足，必须包含小写英文字符、大写英文字符、数字(同一字符或者数字不可连续)且长度必须是8-16位
                error_msg = _('password complexity requirements')
                return FailResponse(str(error_msg))

        times = get_system_setting(DISABLE_PASSWORD_DUPLICATION_TIMES)
        if times:
            user_password_history = UserPasswordHistory.objects.filter(user__username=user_name).order_by(
                '-created_date')[:int(times)]

            for history in user_password_history:
                if history.md5_password == md5_password:
                    # Translators: 密码已经在最近n次中被使用过，请更换其他密码
                    error_msg = _('password used %(num)s times') % {'num': times}
                    return FailResponse(str(error_msg))

        if re.match('^.+@.+$', user_name):  # 邮箱登录正则
            try:
                user = User.objects.get(email__exact=user_name)
            except User.DoesNotExist:
                return FailResponse(str(MSG_50001_ERROR_USER))
        else:  # 用户名登录
            try:
                user = User.objects.get(username__exact=user_name)
            except User.DoesNotExist:
                return FailResponse(str(MSG_50001_ERROR_USER))

        if user.check_password(old_password):
            days = get_system_setting(PASSWORD_VALID_DAYS)
            user.set_password(new_password)
            curr_date = datetime.now().date()
            user.init_status = False
            user.valid_date = curr_date
            user.invalid_date = curr_date + timedelta(days=int(days))
            user.save()
            UserPasswordHistory.objects.create(user=user, md5_password=md5_password)
            return SuccessResponse()
        else:
            # Translators: 原始密码错误
            error_msg = _('the original password is wrong')
            return FailResponse(str(error_msg))


class UpdateAvatar(APIView):
    """
    头像更新 API
    方法：POST
    参数：avatar （图片）
    """

    @transaction.atomic
    def post(self, request):
        user = request.user

        avatar = request.FILES.get('avatar')

        file_name = "A" + str(uuid.uuid4()) + '.PNG'

        upload_path = "media/avatar"

        create_folder(upload_path)

        file_path = os.path.join(upload_path, file_name)

        with open(file_path, 'wb') as f:
            for i in avatar.chunks():
                f.write(i)

        avatar_str = "avatar/" + file_name
        user.avatar = avatar_str
        user.save()
        return SuccessResponse({"avatar": file_path})
